﻿using System.Text;
using System.Text.RegularExpressions;

namespace TfsCloudDeploy.Workflow.Core
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using Microsoft.TeamFoundation;
    using Microsoft.TeamFoundation.VersionControl.Client;

    /// <summary>
    /// A set of utility methods that exist in some form as internal utilities inside of:
    /// - Microsoft.TeamFoundation.Build.Common.BuildCommonUtil (Microsoft.TeamFoundation.Build.Common, Version=10.0.0.0)
    /// - Microsoft.TeamFoundation.Build.Controls.VersionControlHelper (Microsoft.TeamFoundation.Build.Controls, Version=10.0.0.0)
    /// Modified to accommodate our different approach.
    /// </summary>
    public class VersionControlHelper
    {
        #region Constants

        private static Regex s_envRegex = new Regex(@"\$\(([^)]+)\)", RegexOptions.Singleline);
        private static readonly string s_sourceDir = "$(SourceDir)";
        private static readonly string s_depthOneString = "*";

        #endregion

        #region Public Utility Methods

        public static ServerMapping<string>[] GetWorkspaceMappingsFromVersionedServerMappings(VersionedServerMapping[] versionedServerMappings, IDictionary<string, string> additionalVariableReplacements)
        {
            ServerMapping<string>[] serverMappings = new ServerMapping<string>[versionedServerMappings.Length];
            for (int i = 0; i < versionedServerMappings.Length; i++)
            {
                serverMappings[i] = new ServerMapping<string>(
                    GetSanitizedServerItem(versionedServerMappings[i].ServerItem),
                    versionedServerMappings[i].MappingType == WorkingFolderType.Map ? (string.IsNullOrWhiteSpace(versionedServerMappings[i].LocalItem) ? versionedServerMappings[i].LocalItem : ExpandEnvironmentVariables(versionedServerMappings[i].LocalItem, additionalVariableReplacements)) : null,
                    versionedServerMappings[i].MappingType,
                    GetServerItemDepth(versionedServerMappings[i].ServerItem),
                    versionedServerMappings[i].BaselineVersion);
            }

            return serverMappings;
        }

        public static string GetSanitizedServerItem(string serverItem)
        {
            if (string.IsNullOrWhiteSpace(serverItem))
            {
                return serverItem;
            }

            if (serverItem.EndsWith(DepthOneString))
            {
                return serverItem.Substring(0, serverItem.Length - DepthOneString.Length);
            }
            return serverItem;
        }

        public static RecursionType GetServerItemDepth(string serverItem)
        {
            if (string.IsNullOrWhiteSpace(serverItem))
            {
                return RecursionType.None;
            }

            if (serverItem.EndsWith(DepthOneString))
            {
                return RecursionType.OneLevel;
            }
            return RecursionType.Full;
        }

        public static string ExpandSourceDir(string inputString, string sourcesDirectory)
        {
            if (string.IsNullOrWhiteSpace(inputString))
            {
                return string.Empty;
            }

            if (string.IsNullOrWhiteSpace(sourcesDirectory))
            {
                return inputString;
            }

            return inputString.Replace(SourceDirEnvironmentVariable, sourcesDirectory);
        }

        public static string ExpandEnvironmentVariables(string inputStr)
        {
            return ExpandEnvironmentVariables(inputStr, null);
        }

        public static string ExpandEnvironmentVariables(string inputStr, IDictionary<string, string> additionalVariableReplacements)
        {
            if (string.IsNullOrWhiteSpace(inputStr))
            {
                return string.Empty;
            }

            StringBuilder builder = new StringBuilder(inputStr);
            MatchCollection matchs = s_envRegex.Matches(inputStr);
            for (int i = matchs.Count - 1; i >= 0; i--)
            {
                if (matchs[i].Success)
                {
                    string environmentVariable = Environment.GetEnvironmentVariable(matchs[i].Groups[1].Value);
                    if (((environmentVariable == null) && (additionalVariableReplacements != null)) && !additionalVariableReplacements.TryGetValue(matchs[i].Groups[1].Value, out environmentVariable))
                    {
                        additionalVariableReplacements.TryGetValue(matchs[i].Value, out environmentVariable);
                    }
                    if (environmentVariable != null)
                    {
                        builder.Replace(matchs[i].Groups[0].Value, environmentVariable, matchs[i].Index, matchs[i].Length);
                    }
                }
            }
            return builder.ToString();
        }

        #endregion

        #region Public Properties

        public static string SourceDirEnvironmentVariable
        {
            get
            {
                return s_sourceDir;
            }
        }

        public static string DepthOneString
        {
            get
            {
                return s_depthOneString;
            }
        }

        #endregion
    }
}
